/**
*	@class Vector3
*
*	@brief This class implements a 3D Vector object. This class is mainly used to manipulate objects within a 3D space.
*
*	@author William McVicar
*/

#pragma once

#ifndef __VECTOR3_BASIC_H_INCLUDED__
#define __VECTOR3_BASIC_H_INCLUDED__

#ifndef PROTEIN_USE_SIMD

#pragma warning( disable : 4324 )
#pragma warning( disable : 4201 )

// Library Includes

// Local Includes
#include "MathCommon.h"

// Types

// Constants

// Prototypes

namespace Protein
{

template <class Real>
class Vector3
{

public:

  Vector3();
	Vector3( Real x, Real y, Real z );
	Vector3( Real val );
	Vector3( const Vector3& other );
	Vector3( Real* in );
	~Vector3();

  void                    set( Real x, Real y, Real z );
  void                    set( Real val );

  Vector3&                operator=( const Vector3& rhs );

	Vector3	                operator+( const Vector3& rhs ) const;
	Vector3	                operator-( const Vector3& rhs ) const;
	Vector3	                operator*( Real rhs ) const;
	Vector3	                operator/( Real rhs ) const;
	Vector3	                operator-() const;

	Vector3&	              operator+=( const Vector3& rhs );
	Vector3&	              operator-=( const Vector3& rhs );
	Vector3&	              operator*=( Real rhs );
	Vector3&	              operator/=( Real rhs );

	bool			              operator==( const Vector3& rhs ) const;
	bool			              operator!=( const Vector3& rhs ) const;
	bool			              operator> ( const Vector3& rhs ) const;
	bool			              operator< ( const Vector3& rhs ) const;
	bool			              operator>=( const Vector3& rhs ) const;
	bool			              operator<=( const Vector3& rhs ) const;

	Real			              dot( const Vector3& in ) const;
	Vector3		              cross( const Vector3& in ) const;
  Vector3                 unitCross( const Vector3& in ) const;
	Real			              length() const;
	Real			              lengthSqr() const;

	void			              normalise();
	Vector3			            normalised() const;

	Real			              distance( const Vector3& in ) const;
	Real			              distanceSqr( const Vector3& in ) const;

	static Real	            dot( const Vector3& a, const Vector3& b );
	static Vector3	        cross( const Vector3& a, const Vector3& b );
  static Vector3          unitCross( const Vector3& a, const Vector3& b );
	static Real	            length( const Vector3& in );
	static Real	            lengthSqr( const Vector3& in );
	static Real	            distance( const Vector3& a, const Vector3& b );
	static Real	            distanceSqr( const Vector3& a, const Vector3& b );

	static const Vector3    Zero;  
	static const Vector3    i;	    
	static const Vector3    j;	    
	static const Vector3    k;	    
	static const Vector3    negi;	
	static const Vector3    negj;	
	static const Vector3    negk;

  union
	{
		struct
    { 
      Real x;
      Real y;
      Real z; 
    };

	  Real m_components[3];
  };
};

template < class Real >
Vector3<Real> operator*( Real val, const Vector3<Real>& in );

#include "Vector3_Basic.inl"

typedef Vector3<f32> Vector3f;
typedef Vector3<f64> Vector3d;

}

#pragma warning( default : 4201 )
#pragma warning( default : 4324 )

#endif // PROTEIN_USE_SIMD
#endif // __VECTOR3_H_